/*
 * 用户认证控制器
 * 位于包：org.example.lethear.controller
 * 
 * 这个控制器负责处理所有与用户认证相关的HTTP请求，包括：
 * 1. 用户注册
 * 2. 用户登录
 * 3. JWT令牌刷新
 * 4. 用户登出
 * 5. 密码修改
 * 6. 用户名/邮箱可用性检查
 * 
 * 这个控制器是用户认证系统的入口点，负责：
 * - 接收HTTP请求
 * - 验证请求参数
 * - 调用业务服务层
 * - 返回统一格式的响应
 * 
 * 大部分接口都是公开的（不需要认证），但修改密码等敏感操作需要用户先登录。
 */
package org.example.lethear.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.example.lethear.dto.auth.*;
import org.example.lethear.service.AuthService;
import org.example.lethear.utils.Result;
import org.springframework.web.bind.annotation.*;

/**
 * 用户认证控制器
 * 
 * @Tag - Swagger文档标签，用于API文档分组
 * @RestController - 标识这是一个REST控制器，返回JSON格式数据
 * @RequestMapping - 指定控制器的基础URL路径为/auth
 * @RequiredArgsConstructor - Lombok注解，自动生成构造函数注入依赖
 */
@Tag(name = "用户认证", description = "用户登录、注册、登出等认证相关接口")
@RestController
@RequestMapping("/auth")
@RequiredArgsConstructor
public class AuthController {
    
    // 认证服务，处理认证相关的业务逻辑
    private final AuthService authService;
    
    /**
     * 用户注册接口
     * 
     * 处理新用户的注册请求，完成以下操作：
     * 1. 验证注册信息的有效性
     * 2. 检查用户名和邮箱的唯一性
     * 3. 创建新用户账号
     * 4. 生成JWT令牌
     * 5. 返回认证响应
     * 
     * 这个接口是公开的，无需认证即可访问
     * 
     * @param request 用户注册请求对象，包含用户名、邮箱、密码等信息
     * @return Result<AuthResponse> 包含JWT令牌和用户信息的响应
     */
    @Operation(summary = "用户注册", description = "新用户注册账号")
    @PostMapping("/register")
    public Result<AuthResponse> register(@Valid @RequestBody RegisterRequest request) {
        // 1. 调用认证服务处理注册逻辑
        // @Valid注解会自动验证请求参数的有效性
        AuthResponse response = authService.register(request);
        
        // 2. 返回成功响应
        return Result.success("注册成功", response);
    }
    
    /**
     * 用户登录接口
     * 
     * 处理用户登录请求，完成以下操作：
     * 1. 验证用户名/邮箱和密码
     * 2. 检查用户账号状态
     * 3. 生成JWT令牌
     * 4. 更新最后登录时间
     * 5. 返回认证响应
     * 
     * 这个接口是公开的，无需认证即可访问
     * 支持使用用户名或邮箱登录
     * 
     * @param request 用户登录请求对象，包含用户名/邮箱和密码
     * @return Result<AuthResponse> 包含JWT令牌和用户信息的响应
     */
    @Operation(summary = "用户登录", description = "用户登录获取访问令牌")
    @PostMapping("/login")
    public Result<AuthResponse> login(@Valid @RequestBody LoginRequest request) {
        // 1. 调用认证服务处理登录逻辑
        // AuthService会验证用户凭证并生成JWT令牌
        AuthResponse response = authService.login(request);
        
        // 2. 返回成功响应
        return Result.success("登录成功", response);
    }
    
    /**
     * 刷新访问令牌接口
     * 
     * 使用刷新令牌获取新的访问令牌，完成以下操作：
     * 1. 验证刷新令牌的有效性
     * 2. 检查用户状态
     * 3. 生成新的访问令牌
     * 4. 返回认证响应
     * 
     * 这个接口是公开的，但需要提供有效的刷新令牌
     * 
     * @param request 刷新令牌请求对象，包含刷新令牌
     * @return Result<AuthResponse> 包含新的访问令牌和用户信息的响应
     */
    @Operation(summary = "刷新令牌", description = "使用刷新令牌获取新的访问令牌")
    @PostMapping("/refresh")
    public Result<AuthResponse> refreshToken(@Valid @RequestBody RefreshTokenRequest request) {
        // 1. 调用认证服务处理令牌刷新逻辑
        // AuthService会验证刷新令牌并生成新的访问令牌
        AuthResponse response = authService.refreshToken(request);
        
        // 2. 返回成功响应
        return Result.success("令牌刷新成功", response);
    }
    
    /**
     * 用户登出接口
     * 
     * 处理用户登出请求。由于使用JWT无状态认证，
     * 服务器端不需要维护会话状态，登出主要是前端清除令牌。
     * 
     * 在更完善的系统中，这里可能会：
     * 1. 将令牌加入黑名单
     * 2. 记录登出日志
     * 3. 清除相关缓存
     * 
     * 这个接口需要用户认证
     * 
     * @return Result<Void> 登出结果
     */
    @Operation(summary = "用户登出", description = "用户登出，清除认证状态")
    @PostMapping("/logout")
    public Result<Void> logout() {
        // 1. 由于使用JWT，服务器端不需要特殊的登出处理
        // 前端收到这个响应后会清除本地存储的令牌
        
        // 2. 返回成功响应
        return Result.success("登出成功");
    }
    
    /**
     * 修改密码接口
     * 
     * 处理用户修改密码请求，完成以下操作：
     * 1. 验证用户身份（通过JWT令牌）
     * 2. 验证原密码
     * 3. 更新为新密码
     * 4. 返回操作结果
     * 
     * 这个接口需要用户认证
     * 
     * @param request 密码修改请求对象，包含原密码、新密码和确认密码
     * @return Result<Void> 密码修改结果
     */
    @Operation(summary = "修改密码", description = "用户修改登录密码")
    @PostMapping("/change-password")
    public Result<Void> changePassword(@Valid @RequestBody PasswordChangeRequest request) {
        // 1. 调用认证服务处理密码修改逻辑
        // AuthService会验证原密码并更新为新密码
        authService.changePassword(request);
        
        // 2. 返回成功响应
        return Result.success("密码修改成功");
    }
    
    /**
     * 检查用户名可用性接口
     * 
     * 检查指定的用户名是否可以使用，用于：
     * 1. 注册表单的实时验证
     * 2. 用户名重复检查
     * 3. 提供用户友好的提示
     * 
     * 这个接口是公开的，无需认证即可访问
     * 
     * @param username 要检查的用户名
     * @return Result<Boolean> true表示可用，false表示已被使用
     */
    @Operation(summary = "检查用户名可用性", description = "检查用户名是否可以使用")
    @GetMapping("/check-username")
    public Result<Boolean> checkUsernameAvailable(@RequestParam String username) {
        // 1. 调用认证服务检查用户名可用性
        boolean available = authService.isUsernameAvailable(username);
        
        // 2. 返回检查结果
        return Result.success("检查完成", available);
    }
    
    /**
     * 检查邮箱可用性接口
     * 
     * 检查指定的邮箱是否可以使用，用于：
     * 1. 注册表单的实时验证
     * 2. 邮箱重复检查
     * 3. 提供用户友好的提示
     * 
     * 这个接口是公开的，无需认证即可访问
     * 
     * @param email 要检查的邮箱地址
     * @return Result<Boolean> true表示可用，false表示已被使用
     */
    @Operation(summary = "检查邮箱可用性", description = "检查邮箱是否可以使用")
    @GetMapping("/check-email")
    public Result<Boolean> checkEmailAvailable(@RequestParam String email) {
        // 1. 调用认证服务检查邮箱可用性
        boolean available = authService.isEmailAvailable(email);
        
        // 2. 返回检查结果
        return Result.success("检查完成", available);
    }
} 